/*
 * Copyright 2009 Gal Dolber
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.dragdrop.client.impl;

import com.google.gwt.event.dom.client.MouseEvent;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.dragdrop.client.DragController;

public class RotateImpl extends DragProxyImpl {

	private double angle;

	double degreeRadian = 180 / Math.PI;

	private double relativeX;

	private double relativeY;

	private double radians;

	public double getAngle() {
		return angle;
	}

	public double getRadians() {
		return radians;
	}

	public double getRelativeX() {
		return relativeX;
	}

	public double getRelativeY() {
		return relativeY;
	}

	@Override
	public void onDragMove(DragController controller) {
		super.onDragMove(controller);

		MouseEvent<?> event = controller.getCurrentEvent();

		Widget widget = controller.getWidget();
		Widget handler = controller.getHandler();
		
		// TODO detect css translate propertys
		relativeX = event.getRelativeX(widget.getElement()) - widget.getOffsetWidth()/2 + widget.getOffsetWidth()*0.5;
		relativeY = event.getRelativeY(widget.getElement()) - widget.getOffsetHeight()/2 + widget.getOffsetHeight()*0.5;

		angle = calculateAngle(relativeX, relativeY);
		
		if (!handler.equals(widget)) {
			
			// Relative angle to the handler
			double dx = getCenterX(handler) - getCenterX(widget);
			double dy = getCenterY(handler) - getCenterY(widget);
			double correctAngle = calculateAngle(dx, dy);
			
			angle -= correctAngle;
		}
		
		radians = angle / degreeRadian;

		onRotateChange(controller);
	}

	/**
	 * @param handler
	 * @return
	 */
	protected double getCenterX(Widget widget) {
		return widget.getAbsoluteLeft() + widget.getOffsetWidth()/2;
	}
	
	/**
	 * @param handler
	 * @return
	 */
	protected double getCenterY(Widget widget) {
		return widget.getAbsoluteTop() + widget.getOffsetHeight()/2;
	}

	private double calculateAngle(double relativeX, double relativeY) {
		double angle = Math.atan(relativeY / relativeX) * degreeRadian;

		// Region 3
		if (relativeX < 0 && relativeY > 0)
			angle = 180 + angle;

		// Region 1
		else if (relativeX < 0 && relativeY < 0)
			angle = 180 + angle;

		// Region 2
		else if (relativeX > 0 && relativeY < 0)
			angle = 360 + angle;
		
		return angle;
	}
	
	/**
	 * Implement on child
	 * @param controller
	 */
	public void onRotateChange(DragController controller) {
	}
}
